home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 5 / BBS in a Box -Volume V (BBS in a Box) (April 1992).iso / Files / Prog / M / MacOberon.cpt / MacOberonDoc.sit / OG4.Text (.txt) < prev    next >
Encoding:
Oberon Text  |  1990-11-07  |  51.0 KB  |  997 lines  |  [.Ob./.Ob*]

  1. Syntax24.Scn.Fnt
  2. Syntax20.Scn.Fnt
  3. Syntax14.Scn.Fnt
  4. Syntax10.Scn.Fnt
  5. Syntax16.Scn.Fnt
  6. Syntax14i.Scn.Fnt
  7. Syntax12i.Scn.Fnt
  8. Syntax12.Scn.Fnt
  9. MACOBERON REFERENCE MANUAL
  10. Michael Franz
  11. SUMMARY
  12. MacOberon is an implementation of the Oberon system for Apple
  13. Macintosh II computers, closely resembling the original implementation on
  14. the personal workstation Ceres.  This document supplements the existing
  15. Oberon documentation and describes those aspects in which MacOberon
  16. differs from or extends standard Oberon.
  17. TABLE OF CONTENTS
  18. 1.  Installation and Activation
  19. 1.1.  Files Required by MacOberon
  20. 1.2.  Activation from the Macintosh Finder
  21. 2.  MacOberon Compiler
  22. 2.0.  Introduction
  23. 2.1.  Compiler Options
  24. 2.2.  Module SYSTEM
  25. 2.3.  Data Representation and Alignment
  26. 2.4.  Code Procedures
  27. 2.5.  List of Compiler Errors
  28. 3.  MacOberon Run_Time System
  29. 3.1.  List of MacOberon Run_Time Errors
  30. 3.2.  List of Macintosh File System Errors
  31. 4.  MacOberon Library
  32. 4.0.  Overview
  33. 4.1.  Module Display
  34. 4.2.  Module Input
  35. 4.3.  Modules FileSys and Files
  36. 4.4.  Module System
  37. 4.5.  Module Edit
  38. 5.  Macintosh Toolbox Interfaces
  39. 5.0.  Overview
  40. 5.1.  Macintosh Toolbox Types
  41. 5.2.  Macintosh QuickDraw
  42. 5.3.  Macintosh Window Manager
  43. 5.4.  A Sample Application
  44. Figures
  45. Appendix
  46. 1.  INSTALLATION AND ACTIVATION
  47. 1.1.  Files Required by MacOberon
  48. MacOberon consists of a number of files which have different purposes.  All of these
  49. files have to be contained in a single folder on the Macintosh desktop.
  50. Most important of all, there is the MacOberon application.  This contains the module
  51. loader and the memory management system, both of which are coded in Assembly
  52. Language for performance reasons.  The MacOberon application must always be
  53. present for executing code in Oberon modules.
  54. Besides the MacOberon application, several Oberon object files are supplied.  The
  55. table below displays the basic Oberon modules and their approximate position in the
  56. module hierarchy.  The names of the corresponding object files consist of the module
  57. names with the suffix ".ObM" (for Object File Motorola 68020) appended to them.
  58.         System        Edit
  59.             TextFrames
  60.             MenuViewers
  61.         Oberon        Printer
  62.         Texts
  63.         Fonts    Viewers
  64. Modules    Reals    Files    Display    Input
  65. Kernel        FileSys
  66. These modules constitute the standard MacOberon system and their object files are
  67. required for using the normal Oberon environment on the Macintosh.  The MacOberon
  68. compiler consists of modules which have names starting with either "OP" or "MOP". 
  69. The use of module Fonts further requires the default font file to be present.  This file is
  70. named "Syntax10.Scn.Fnt".
  71. Several supplementary files are also distributed with MacOberon.  There are some
  72. font files in addition to the default font which can be recognized by a characteristic icon
  73. (Fig. 1) and the file name suffix ".Scn.Fnt" (for Screen Font).  The remaining files are
  74. either symbol files used by the compiler or text files.  Some of these text files contain
  75. documentation while others, recognizable by file names ending in ".Tool", contain lists
  76. of commands that may be executed simply by pointing the mouse and pressing a key. 
  77. The file "System.Tool" will automatically be opened at startup.
  78. MacOberon may be used for the creation of stand_alone application packages that
  79. use none of the services of the standard modules and therefore do not require them to
  80. be present.  Only the appropriate modules and the MacOberon application are needed
  81. for using these programs.
  82. 1.2.  Activation from the Macintosh Finder
  83. MacOberon is started by double_clicking on any Oberon file from the Macintosh Finder
  84. (or MultiFinder).  Unless the Option key is pressed simultaneously, MacOberon will
  85. then perform its default startup sequence.  It will attempt to load the module "Oberon"
  86. and all modules imported by it.  Module Oberon ends its initialization sequence by
  87. explicitly loading module "System" which causes the remaining standard modules
  88. (except for "Edit" and "Printer") to be added.  Finally, the Main Loop of Oberon is
  89. entered, polling the mouse and keyboard for input.
  90. The default loading process may be overruled.  By double_clicking on an object file
  91. while holding down the Option key, a user may designate an Oberon module to be
  92. loaded directly from the Macintosh Finder.  In this case, only those modules that are
  93. imported by the selected module are processed by the loader.  This mechanism
  94. facilitates the creation of more conventional Macintosh applications that utilize only
  95. Toolbox interface modules.
  96. 2.  MACOBERON COMPILER
  97. 2.0.  Introduction
  98. The MacOberon compiler differs from most other compilers for the Macintosh, in that
  99. it uses a different data alignment and different procedure calling conventions than the
  100. Macintosh operating system and Toolbox.  This improves the execution speed of most
  101. programs.  However, it also demands some extra attention from programmers wishing
  102. to interface directly to the Macintosh operating system.  Chapters 2.3. and 2.4. are for
  103. the benefit of this category of programmer exclusively and may be passed over by all
  104. others.
  105. 2.1.  Compiler Options
  106. The MacOberon compiler accepts a number of options, which may be activated
  107. independently of each other.  The following table lists the available options.
  108. Selector    Function
  109.     s    enable generation of a new symbol file
  110.     x    disable index checks
  111.     n    disable NIL checks of pointer variables
  112.     p    disable NIL checks of procedure variables
  113.     t    disable type checks
  114.     r    enable range checks
  115.     g    suppress garbage collection after compiling the current module
  116. Each file parameter may be followed by a slash ("/") and a list of option selectors.
  117. Examples:
  118.     Compiler.Compile */n
  119.     Compiler.Compile File1.Mod/sg File2.Mod/sxnt ~
  120. Unless the /g option is used, the garbage collector will be called between the
  121. compilation of any two modules.  Apart from recycling memory, this will close all files
  122. that were opened during compilation but are no longer in use, preventing an overflow
  123. of the file access path table.  Exhaustion of available memory occurs far more rarely
  124. during compilation than a lack of file access paths.
  125. 2.2.  Module SYSTEM
  126. Module SYSTEM for the Motorola 68020 microprocessor provides some low_level
  127. operations via procedures which are compiled as in_line code.  The interface to the
  128. MC68020 version of module SYSTEM is identical to that for the National Semiconductor
  129. 32x32 microprocessor but the semantics of some of the procedures are subtly different,
  130. reflecting a different machine architecture.
  131. In the following tables, v stands for a variable, x, y, a and n stand for expressions and
  132. T for a type.
  133. 2.2.1.  Function Procedures
  134. Name    Argument Types    Result Type    Function
  135. ADR(v)    any    LONGINT    address of variable v
  136. BIT(a, n)    a: LONGINT    BOOLEAN    bit n of Mem[a] (0 <= n <= 7)
  137.     n: integer constant
  138. CC(n)    n: integer constant    BOOLEAN    CPU condition n (0 <= n < 16)
  139.             FPU condition -n  (0 > n > -32)
  140. LSH(x, n)    x, n: integer type    LONGINT    logical shift (LSL, LSR)
  141. ROT(x, n)    x, n: integer type    LONGINT    rotation (ROL, ROR)
  142. VAL(T, x)    T, x: any type    T    x interpreted as of type T
  143. 2.2.2.  Proper Procedures
  144. Name    Argument Types    Function
  145. GET(a, v)    a: LONGINT; v: any basic type    v := Mem[a]
  146. PUT(a, x)    a: LONGINT; x: any basic type    Mem[a] := x
  147. GETREG(n, v)    n: integer constant; v: any basic type    v := Rn  (see explanation below)
  148. PUTREG(n, x)    n: integer constant; x: any basic type    Rn := x  (see explanation below)
  149. MOVE(a0, a1, n)    a0, a1, n: integer type, n > 0    Mem[a1+i] := Mem[a0+i], i = 0..n-1
  150. NEW(v, n)    v: any pointer type    allocate a storage block of n bytes    
  151.     n: integer type    and assign its address to v
  152. The register number supplied to SYSTEM.PUTREG and SYSTEM.GETREG is interpreted as
  153. follows:  If v is of a real type and (0 <= n <= 7), then floating point register Fn is used. 
  154. Otherwise, for (0 <= n <= 7) data register Dn is used, and for (8 <= n <= 15) address
  155. register An-8 is used.
  156. 2.3.  Data Representation and Alignment
  157. By default, the MacOberon compiler employs a different data layout and different
  158. calling conventions than the Macintosh operating system and Toolbox.  The Toolbox
  159. conventions are also supported but their use has to be be explicitly activated by special
  160. compiler hints embedded in the source program.  In order to distinguish between the
  161. two variants, we will in the following refer to procedures and data structures that
  162. incorporate these compiler hints as "interfacing" and all others as "pure".
  163. Observance of the Toolbox conventions is only required when calling operating
  164. system routines directly.  Very few programmers will ever need to do this.  Instead, most
  165. of them will prefer to use the standard Oberon libraries or the Toolbox interface modules
  166. provided.  Although these interface modules themselves make use of the Toolbox
  167. conventions, this is encapsulated within the modules and need not concern their
  168. clients.
  169. 2.3.1.  Internal Representation of Data Types Under the Two Different Protocols
  170. Data Type    Toolbox Representation    Oberon Default Representation
  171. SHORTINT    not used    1 Byte signed
  172. INTEGER    2 Bytes signed    2 Bytes signed
  173. LONGINT    4 Bytes signed    4 Bytes signed
  174. BYTE    2 Bytes (value in low byte)    1 Byte unsigned
  175. CHAR    2 Bytes (ASCII code in low byte)    1 Byte unsigned
  176. BOOLEAN    1 Byte (Boolean value in Bit 0)    1 Byte (0H=FALSE, 0FFH=TRUE)
  177. SET    (Pascal SET OF ...)    4 Bytes unsigned ({0}=1H, ...)
  178. REAL    4 Bytes IEEE single format    4 Bytes IEEE single format
  179. LONGREAL    8 Bytes IEEE double format    8 Bytes IEEE double format
  180. Pointer Type    4 Bytes (NIL = 0)    4 Bytes (NIL = 0)
  181. Procedure Type    4 Bytes    4 Bytes (NIL = 0)
  182. Oberon uses a different format than the Macintosh Toolbox for representing the data
  183. types BYTE and CHAR.  The Toolbox representation can be simulated by using the data
  184. type INTEGER.  The MacOberon compiler forbids the use of the types BYTE and CHAR for
  185. parameters in interfacing procedures and for fields of records or elements of arrays that
  186. are stored in Toolbox representation.  In these cases, the variables or fields in question
  187. have to be declared as INTEGER.  The predefined function procedure ORD() may be
  188. used for obtaining the correct INTEGER equivalents of bytes and characters.
  189.     Toolbox Representation    Oberon Default Representation
  190. Data Alignment    type_size modulo 2    type_size modulo 4
  191. Parameter Alignment    word    longword
  192. Record Padding    no padding added    padded to longword boundary
  193. Packed Data Structures    (Pascal PACKED ...)    simulated by programmer
  194. 2.3.2.  Parameters and Function Results of Pure Oberon Procedures
  195. The following rules apply to parameters and function results of pure procedures:
  196. 1.    All parameters are longword_aligned.
  197. 2.    Function results are returned in registers.  REAL and LONGREAL results are
  198.     returned in floating_point register F0, pointer_valued results are returned in
  199.     address register A0 and all other types of result are returned in data register D0.
  200. 3.    For variable parameters, the address of the variable is passed.  If the variable
  201.     parameter is a record, an extra parameter describing the dynamic type of the
  202.     record is added.
  203. 4.    For all dynamic array parameters, an additional parameter describing the length
  204.     of the innermost dimension is passed, plus two additional parameters for
  205.     every higher dimension, describing the length of the array in that dimension and
  206.     the compounded size of all smaller dimensions.
  207. 5.    Dynamic array value parameters are copied by the callee.  A pointer to the array is
  208.     passed along with the dimension data.
  209. 2.3.3.  Parameters and Function Results of Interfacing Oberon Procedures
  210. The following rules apply to parameters and function results of interfacing procedures:
  211. 1.    All parameters are word_aligned.
  212. 2.    Function results are returned on the stack.  Space for results is reserved by the
  213.     caller before any parameters are passed.
  214. 3.    For variable parameters, the address of the variable is passed.
  215. 4.    REAL and LONGREAL value parameters are converted to the IEEE extended
  216.     precision (96 bit) format by the caller and a pointer to this value is passed to the
  217.     procedure.
  218. 5.    Array and record_typed value parameters are copied by the caller if the size of the
  219.     structure is smaller than 5 bytes.  Otherwise, they are copied by the callee and a
  220.     pointer to the structure is passed.
  221. 6.    Dynamic arrays are not supported.
  222. 2.3.4.  Using Interfacing Data Types in MacOberon
  223. Interfacing Data structures which have an internal layout according to Toolbox
  224. conventions are marked by a Plus symbol ("+") following one of the reserved words
  225. ARRAY, POINTER or RECORD.
  226. Example:
  227.     TYPE Point = RECORD +
  228.         top, left, bottom, right: INTEGER
  229.     END;
  230. The MacOberon compiler observes the following rules when Toolbox data types are
  231. used in Oberon programs:
  232. 1.    The fields of interfacing records and elements of interfacing arrays must be
  233.     simple types (excluding CHAR and BYTE) or must themselves be interfacing
  234.     structures.  Interfacing records may not extend pure records.  On the other hand,
  235.     pure structure may contain interfacing substructures and may extend them.
  236. 2.    Pointers to interfacing structures must be declared as interfacing pointers, i.e.
  237.     with a Plus mark following the POINTER reserved word.  These pointers are
  238.     invisible to the garbage collector.  Calls to the standard procedure NEW are
  239.     translated into calls of the operating system trap _NewPtr by the compiler.  A
  240.     programmer need not call _NewPtr himself or be concerned about the size of the
  241.     data to be allocated.  Deallocation is the responsibility of the programmer.
  242. 3.    Type guards applied to interfacing data structures will never fail.  Type extension
  243.     may thus be used for simulating variant records.
  244. 2.4.  Code Procedures
  245. The MacOberon compiler allows for the declaration of in_line code procedures, which
  246. are especially useful for representing unimplemented processor instructions by which
  247. Macintosh Toolbox routines are activated.  Code procedures are marked by a Minus
  248. symbol ("-") following the reserved word PROCEDURE.  Instead of a procedure body, an
  249. arbitrary byte sequence (which may be empty) is given after the formal parameter list. 
  250. This byte sequence is inserted in the object code instead of a regular procedure call
  251. after space has been reserved for function results (if any) and all parameters have been
  252. pushed onto the stack.
  253. Example:
  254.     PROCEDURE - EmptyRgn*(rgn: RgnHandle): BOOLEAN  0A8H, 0E2H;
  255. Code procedures may be exported, in which case the associated byte sequence is
  256. contained in the symbol file so that it may be included in client modules.  Macintosh
  257. Toolbox calling conventions are observed for code procedures.  Only parameters of
  258. simple types or interfacing types may be passed to them.
  259. 2.5.  List of MacOberon Compiler Errors
  260. 2.5.1.  Incorrect Use of Oberon Language
  261.   0    undeclared identifier
  262.   1    multiply defined identifier
  263.   2    illegal character in number
  264.   3    illegal character in string
  265.   4    identifier does not match procedure name
  266.   5    comment not closed
  267.   9    "=" expected
  268. 10    identifier expected
  269. 12    type definition starts with incorrect symbol
  270. 13    factor starts with incorrect symbol
  271. 14    statement starts with incorrect symbol
  272. 15    declaration followed by incorrect symbol
  273. 16    MODULE expected
  274. 17    number expected
  275. 18    "." missing
  276. 19    "," missing
  277. 20    ":" missing
  278. 22    ")" missing
  279. 23    "]" missing
  280. 24    "}" missing
  281. 25    OF missing
  282. 26    THEN missing
  283. 27    DO missing
  284. 28    TO missing
  285. 29    "(" missing
  286. 33    ":=" missing
  287. 34    "," or OF expected
  288. 37    identifier expected
  289. 38    ";" missing
  290. 40    END missing
  291. 43    UNTIL missing
  292. 45    EXIT not within loop statement
  293. 47    illegally marked identifier
  294. 48    unsatisfied forward reference
  295. 49    recursive import not allowed
  296. 50    expression should be constant
  297. 51    constant not an integer
  298. 52    identifier does not denote a type
  299. 53    identifier does not denote a record type
  300. 54    result type of procedure is not a basic type
  301. 55    procedure call of a function
  302. 56    assignment to non_variable
  303. 57    pointer not bound to record or array type
  304. 58    recursive type definition
  305. 59    illegal open array parameter
  306. 60    wrong type of case label
  307. 61    inadmissible type of case label
  308. 62    case label defined more than once
  309. 63    index out of bounds
  310. 64    more actual than formal parameters
  311. 65    fewer actual than formal parameters
  312. 66    element types of actual array and formal open array differ
  313. 67    actual parameter corresponding to open array is not an array
  314. 69    parameter must be an integer constant
  315. 73    procedure must have level 0
  316. 77    object is not a record
  317. 78    dereferenced object is not a variable
  318. 79    indexed object is not a variable
  319. 80    index expression is not an integer
  320. 81    index out of specified bounds
  321. 82    indexed variable is not an array
  322. 83    undefined record field
  323. 84    dereferenced variable is not a pointer
  324. 85    guard or test type is not an extension of variable type
  325. 86    guard or test type is not a pointer
  326. 87    guarded or tested variable is neither a pointer nor a VAR_parameter record
  327. 92    operand of IN not an integer, or not a set
  328. 93    set element type is not an integer
  329. 94    operand of & is not of type BOOLEAN
  330. 95    operand of OR is not of type BOOLEAN
  331. 96    operand not applicable to (unary) +
  332. 97    operand not applicable to (unary) -
  333. 98    operand of ~ is not of type BOOLEAN
  334. 100    incompatible operands of dyadic operator
  335. 101    operand type inapplicable to *
  336. 102    operand type inapplicable to /
  337. 103    operand type inapplicable to DIV
  338. 104    operand type inapplicable to MOD
  339. 105    operand type inapplicable to +
  340. 106    operand type inapplicable to -
  341. 107    operand type inapplicable to = or #
  342. 108    operand type inapplicable to relation
  343. 110    operand is not a type
  344. 111    operand inapplicable to (this) function
  345. 112    operand is not a variable
  346. 113    incompatible assignment
  347. 114    string too long
  348. 115    parameter discrepancy between type (or name) of variable (or forward procedure)
  349.     and this procedure
  350. 116    type of variable (or forward procedure) has more parameters than this procedure
  351. 117    type of variable (or forward procedure) has fewer parameters than this procedure
  352. 118    procedure result type of variable (or of forward declaration) differs from result type
  353.     of this procedure
  354. 119    assigned procedure is not global
  355. 120    type of expression following IF, WHILE, or UNTIL is not BOOLEAN
  356. 121    called object is not a procedure (or is an interrupt procedure)
  357. 122    actual VAR_parameter is not a variable
  358. 123    type of actual parameter is not identical with that of formal VAR_parameter
  359. 124    type of result expression differs from that of procedure
  360. 125    type of case expression is neither INTEGER nor CHAR
  361. 126    this expression cannot be a type or a procedure
  362. 127    illegal use of object
  363. 129    unsatisfied forward procedure
  364. 130    WITH clause does not specify a variable
  365. 131    LEN not applied to array
  366. 132    dimension in LEN too large or negative
  367. 133    procedure declaration does not match forward declaration
  368. 150    key inconsistency of imported module
  369. 151    incorrect symbol file
  370. 152    symbol file of imported module not found
  371. 153    object or symbol file not opened (disk full?)
  372. 155    generation of new symbol file not allowed
  373. 2.5.2.  Limitations of MacOberon Implementation
  374. 200    not yet implemented
  375. 201    lower bound of set range greater than higher bound
  376. 202    set element greater  than MAX(SET) or less than 0
  377. 203    number too large
  378. 204    product too large
  379. 205    division by zero
  380. 206    sum too large
  381. 207    difference too large
  382. 208    overflow in arithmetic shift
  383. 209    case range too large
  384. 210    code too long
  385. 211    jump distance too large
  386. 213    too many cases in case statement
  387. 214    too many exit statements
  388. 215    not enough registers: simplify expression
  389. 216    not enough floating_point registers: simplify expression
  390. 217    parameter must be an integer constant
  391. 218    illegal value of parameter  (20 <= p < 256)
  392. 219    illegal value of parameter  (0 <= p < 16)
  393. 220    illegal value of parameter
  394. 222    too many pointers (either global, or in record)
  395. 223    too many record types
  396. 224    too many pointer types
  397. 225    address of pointer variable too large (move forward in text)
  398. 226    too many exported procedures
  399. 227    too many imported modules
  400. 228    too many exported structures
  401. 229    too many nested records for import
  402. 230    too many constants (strings) in module
  403. 231    too many link table entries (external procedures)
  404. 232    too many commands in module
  405. 233    record extension hierarchy too high
  406. 240    identifier too long
  407. 241    string too long
  408. 2.5.3.  Macintosh Toolbox Interface Restrictions
  409. 300    Macintosh Toolbox uses different CHAR and BYTE representation
  410. 301    field of an interfacing type declared as a pure structure
  411. 302    field of an interfacing type declared as a pure pointer
  412. 303    interfacing procedure variables must not have parameters
  413. 304    code procedures must not accept dynamic array parameters
  414. 305    code procedures must not accept pure structures as parameters
  415. 3.  MACOBERON RUN_TIME SYSTEM
  416. 3.1.  List of MacOberon Run_Time Errors
  417.   2    NIL_reference
  418.   3    address error
  419.   4    illegal instruction
  420.   5    division by zero
  421.   6    invalid index
  422.   7    range error in conversion
  423. 13    integer overflow
  424. 14    floating_point overflow
  425. 16    invalid case in CASE statement
  426. 17    function procedure without RETURN statement
  427. 18    type guard check
  428. 19    implied type guard check in record assignment
  429. 20    Macintosh File System error (check OSErr code and consult File System Error table)
  430. 21    too many files open
  431. 22    out of heap space
  432. 30 - 255  Programmed HALT
  433. 3.2.  List of Macintosh File System Errors
  434. -19    read error
  435. -20    write error
  436. -33    directory full
  437. -34    disk full
  438. -35    no such volume
  439. -36    disk I/O error
  440. -37    bad name
  441. -38    file not open
  442. -39    end of file
  443. -40    tried to position to before start of file
  444. -41    memory full or file won't fit
  445. -42    too many files open
  446. -43    file not found
  447. -44    disk is write protected
  448. -45    file is locked
  449. -46    volume is locked
  450. -47    file busy
  451. -48    duplicate file name
  452. 4.  MACOBERON LIBRARY
  453. 4.0.  Overview
  454. Several enhancements are necessary for the standard Oberon libraries to accommodate
  455. some of the peculiarities of the Macintosh environment.  All of the variables and
  456. procedures specified in the "Supplementary Definition" modules below are exported in
  457. addition to those defined in the standard Oberon documentation and should be
  458. thought of as extending the basic Oberon system.
  459. 4.1.  Module Display
  460. SUPPLEMENTARY DEFINITION Display;
  461.         window*: LONGINT;    (* Identification of Oberon screen emulation window *)
  462.         neutralize*, restore*: PROCEDURE;    (* Screen neutralization and restoration, called from Update *)
  463.     (* Emulation of Oberon Screen inside of Macintosh Window *)
  464.         PROCEDURE Show*;
  465.         PROCEDURE Hide*;
  466.         PROCEDURE Update*;    (* Should be called on every update event with theEvent.message=Display.window *)
  467.     (* Pattern Definition *)
  468.         PROCEDURE NewPattern*(W, H: INTEGER; VAR image: ARRAY OF BYTE): Pattern;
  469.         PROCEDURE SetPatternGrey*(pat: Pattern; VAR image: ARRAY OF BYTE);
  470.     (* Off_Line Pattern Accumulation for Acceleration of Display Operations *)
  471.         PROCEDURE OpenCache*(X, Y, W, H: INTEGER);
  472.         PROCEDURE AccumulatePat*(pat: LONGINT; X, Y: INTEGER);
  473.         PROCEDURE TransferCache*(mode: INTEGER);
  474.     (* Restore Standard MacOberon Settings when Changed by Command *)
  475.         PROCEDURE ShowStdMenus*;
  476.         PROCEDURE ShowStdArrow*;
  477. END Display.
  478. MacOberon's module Display exports the window pointer of the Oberon window as a
  479. LONGINT variable.  Whenever an update event is received with a message field equal to
  480. this value, the procedure Display.Update should be activated.
  481. Display.Update itself calls two installed procedures, Display.neutralize and
  482. Display.restore, for removing selections and other marks and redrawing the contents of
  483. the Oberon window.  The procedures that are installed as a default are defined in
  484. module Oberon and shown below.  Users may choose to substitute them by their own
  485. procedures if they wish to use module Display but not Oberon in stand_alone
  486. application packages.  Neutralization prior to redrawing is necessary because the
  487. restore operation is clipped to the intersection of the window contents and the
  488. Window Manager's update region while some drawing is performed in transfer mode
  489. "invert".
  490. PROCEDURE Neutralize;
  491.     VAR M: Oberon.ControlMsg;
  492. BEGIN
  493.     M.id := neutralize; Viewers.Broadcast(M); Oberon.FadeCursor(Oberon.Pointer)
  494. END Neutralize;
  495. PROCEDURE Restore;
  496.     VAR M: Viewers.ViewerMsg;
  497. BEGIN
  498.     M.id := Viewers.suspend; Viewers.Broadcast(M);
  499.     M.id := Viewers.restore; Viewers.Broadcast(M)
  500. END Restore;
  501. The Oberon window may be hidden by a call to Display.Hide and restored by a call to
  502. Display.Show.  It will automatically be made visible in the event of a trap.  Commands
  503. may also change the appearance of the cursor and of menus as they please and
  504. conveniently restore the regular look by the procedures provided.
  505. A standard mechanism is provided for defining Patterns.  The image passed to the
  506. procedure Display.NewPattern should be a standard Macintosh bit image in which the
  507. number of bytes per pixel row is divisible by four.  A Macintosh resource editor may be
  508. used for creating such images and representing them as a series of hexadecimal values.
  509. For grey_scale patterns which need to be replicated, an optional QuickDraw_Pattern
  510. representation may be assigned by use of the procedure Display.SetPatternGrey.  If such
  511. an alternative representation has been defined, QuickDraw_Pattern fill procedures are
  512. used for replication automatically.  Otherwise, replication is executed in an explicit
  513. loop.  Below is an example of a Pattern definition.
  514.     grey: Display.Pattern; img: ARRAY 4 OF LONGINT; qdpat: ARRAY 2 OF LONGINT;    
  515. img[0] := 000000000H; img[1] := 022222222H;
  516. img[2] := 000000000H; img[3] := 088888888H;
  517. grey := Display.NewPattern(32, 4, img);
  518. qdpat[0] := 000220088H; qdpat[1] := 000220088H;
  519. Display.SetPatternGrey(grey, qdpat);
  520. Furthermore, a pattern cache is supported which may be used for accelerating display
  521. operations.
  522. 4.2.  Module Input
  523. SUPPLEMENTARY DEFINITION Input;
  524.         macEvent*: BOOLEAN;    (* TRUE if last MouseDown was handled by Input and should be ignored *)
  525.         backgrounder*: PROCEDURE;    (* Called repeatedly by MultiFinder while MacOberon is in background *)
  526.         notifySuspend*, notifyResume*: PROCEDURE;    (* Multi Finder event signalling *)
  527. END Input.
  528. Due to the architecture of the Macintosh system, applications may receive some events
  529. which relate not to the contents of their windows but to the environment that the
  530. applications run in.  In the case of MacOberon, some of the mouse and keyboard events
  531. obtained from the operating system are actually directed at desk accessories or relate to
  532. menu commands and to the layout of windows on the screen.  These need to be
  533. processed at some lower level and not by the emulated Oberon system.
  534. This is done as a side effect to polling the keyboard in the procedure Input.Available. 
  535. Whenever the procedure Input.Available is called, the Macintosh event queue is
  536. scanned and all pending keyboard events are accumulated into a simulated keyboard
  537. buffer.  While this is done, other types of events, such as update events, MultiFinder
  538. suspend/resume events and desk accessory events, are also extracted and processed.
  539. Since the mouse state is inspected and saved prior to polling the keyboard in the
  540. main loop of module Oberon, we provide a global flag in module Input which signals if
  541. the last mouse event has already been handled and should be ignored by the higher
  542. module.  The main loop in Oberon and all other loops with a similar structure need to
  543. be augmented by the statements printed in boldface below, in order to ensure that all
  544. special mouse events are passed over.
  545. LOOP  Input.Mouse(keys, X, Y);
  546.     IF  Input.Available() > 0  THEN
  547.         ... (* handle character input *) ...
  548.     ELSIF  keys # {}  THEN
  549.         IF  ~Input.macEvent  THEN
  550.             REPEAT  ... (* let Viewers.This(X, Y) handle tracking *) ...  UNTIL keys = {};
  551.         END
  552.     ELSE
  553.         ... (* redisplay mouse if moved or invisible, then execute next Task in Task queue *) ...
  554. User commands may make free use of the procedure Input.Mouse to poll the state of
  555. the mouse button and the simulated additional buttons.  However, care has to be taken
  556. when calling Input.Available because it will access the event queue and remove events
  557. from it.  To be on the safe side, user commands that read the event queue directly
  558. should respond to keyboard events instead of using Input.Available and Input.Read.
  559. The procedure installed in Input.backgrounder is called repeatedly while the
  560. MacOberon application is in the background.  The default background handler is
  561. contained in module Oberon and executes all installed Oberon Tasks in a round_robin
  562. fashion.  Arbitrary procedures may be installed in the procedure variables
  563. Input.notifySuspend and Input.notifyResume which are called when corresponding
  564. MultiFinder events are detected.
  565. Module Input also performs some translations of characters received from the
  566. Macintosh keyboard into their Oberon equivalent.  This applies to umlauted and
  567. accented characters which have different ordinal values in the Macintosh character set
  568. than in the Oberon character set.  The "esszett" key on Macintosh German keyboards is
  569. mapped into two strokes of the "s" key.
  570. 4.3.  Modules Files and FileSys
  571. SUPPLEMENTARY DEFINITION Files;
  572.     PROCEDURE ReadNormBytes*(VAR r: Rider; VAR x: ARRAY OF BYTE; n: LONGINT);
  573.     PROCEDURE WriteNormBytes*(VAR r: Rider; VAR x: ARRAY OF BYTE; n: LONGINT);
  574.     PROCEDURE SetType*(f: File; type, creator: LONGINT);
  575. END Files.
  576. MacOberon's module Files extends the standard definition by a mechanism for writing
  577. data in little_endian byte ordering.  The effect of these procedures is defined as follows:
  578. PROCEDURE ReadNormBytes(VAR r: Files.Rider; VAR x: ARRAY OF BYTE; n: LONGINT);    
  579.     VAR i: LONGINT;
  580. BEGIN  i := LEN(x);
  581.     WHILE  (n > 0) & (i > 0)  DO  DEC(i); DEC(n); Files.Read(r, x[i])  END
  582. END ReadNormBytes;
  583. PROCEDURE WriteNormBytes(VAR r: Files.Rider; VAR x: ARRAY OF BYTE; n: LONGINT);
  584.     VAR i: LONGINT;
  585. BEGIN  i := LEN(x);
  586.     WHILE  n > 0  DO  DEC(i); DEC(n); Files.Write(r, x[i])  END
  587. END WriteNormBytes;
  588. There is also a procedure for setting the Type and Creator properties supported by the
  589. Macintosh file system.
  590. A module FileSys is provided, which implements the low_level file access
  591. mechanism.  Module FileSys exports the file creator and file type values employed by
  592. MacOberon which should be used when changing the type of Oberon files, and a
  593. procedure Enumerate which allows access to the file directory.  The ListProc passed as a
  594. parameter to this procedure will be called for all files in the Oberon directory whose
  595. name starts with the given prefix.
  596. DEFINITION FileSys;   (* Low_Level File Interface *)
  597.     CONST
  598.         FntFile*= 2E466E74H;    (* '.Fnt' Font File *)
  599.         ObjFile*= 2E4F624DH;    (* '.ObM' Object File *)
  600.         RegFile*= 2E4F622EH;    (* '.Ob.' Permanent File *)
  601.         TmpFile*= 2E546D70H;    (* '.Tmp' Temporary File *)
  602.         Creator*= 2E4F622AH;    (* '.Ob*' Created by Oberon *)
  603.     TYPE
  604.         FileName*= RECORD
  605.             l*: SHORTINT;    (* File Name Length *)
  606.             str*: ARRAY 31 OF CHAR    (* File Name Characters *)
  607.         END;
  608.         ListProc*= PROCEDURE(VAR name: ARRAY OF CHAR;
  609.                                                   type, creator, crdat, moddat, length: LONGINT);
  610.         nofAccPaths*: INTEGER;    (* Number of Access Paths in use by Oberon *)
  611.     PROCEDURE Open*(VAR name: FileName; VAR refNum: INTEGER; VAR found: BOOLEAN);
  612.     PROCEDURE Close*(refNum: INTEGER);
  613.     PROCEDURE Read*(refNum: INTEGER; pos, count: LONGINT; VAR buf: FileName);
  614.     PROCEDURE Write*(refNum: INTEGER; pos, count: LONGINT; VAR buf: FileName);
  615.     PROCEDURE GetEOF*(refNum: INTEGER; VAR eof: LONGINT);
  616.     PROCEDURE SetEOF*(refNum: INTEGER; eof: LONGINT);
  617.     PROCEDURE Create*(VAR name: FileName);
  618.     PROCEDURE Delete*(VAR name: FileName; VAR found: BOOLEAN);
  619.     PROCEDURE Rename*(VAR from, to: FileName; VAR found: BOOLEAN);
  620.     PROCEDURE GetDate*(VAR name: FileName; VAR crdat, moddat: LONGINT);
  621.     PROCEDURE SetType*(VAR name: FileName; type, creator: LONGINT);
  622.     PROCEDURE FlushVol*;
  623.     PROCEDURE Enumerate*(VAR prefix: ARRAY OF CHAR; list: ListProc);
  624. END FileSys.
  625. 4.4.  Module System
  626. SUPPLEMENTARY DEFINITION System;
  627.     PROCEDURE Version*;    (* Display version date of this Oberon Release *)
  628.     PROCEDURE Debug*;    (* Call Macintosh Debugger if present *)
  629.     PROCEDURE Quit*;    (* Orderly exit to the Finder, identical to the menu command of the same name *)
  630. END System.
  631. The Macintosh version of Module System adds a command for displaying the version
  632. number of MacOberon in the System.Log viewer.  There are also two commands for
  633. calling the system debugger (by use of the "A9FF" trap), if there is one installed, and for
  634. terminating the Oberon session in an orderly manner, flushing all file buffers and
  635. removing anonymous files on the way.
  636. The commands System.ShowCommands and System.State have been modified to
  637. optionally accept the most recent selection as a parameter.  The commands
  638. System.ShowModules and System.ShowCommands feature a new option "/a" which may
  639. be used for displaying the addresses of modules and command procedures.
  640. The command System.Directory accepts a number of options which may be
  641. activated independently of each other and are listed in the following table.
  642. Selector    Function
  643.     d    display file modification date
  644.     s    display file size in Bytes
  645.     l    disable file type
  646.     a    display all files, including files that were not created by Oberon
  647.     ax    display only files that are foreign Oberon
  648. The file parameter can contain wild_cards ("*") and may be followed by a slash ("/")
  649. and a list of option selectors.
  650. Examples:
  651.     System.Directory *.Mod/sd
  652.     System.Directory *bero*/ax
  653. 4.5.  Module Edit
  654. The Edit.Print command has been modified to facilitate printing to a PostScript file
  655. which may be downloaded to any compatible printer.  The file Oberon.Header.ps
  656. contains macro declarations that are required for printing the output and is prepended
  657. to any PostScript file generated.  Font substitution instructions for translating between
  658. Oberon and PostScript fonts are defined in this file and may be changed freely.  A
  659. Percent symbol ("%") following the PostScript file name indicates that output should be
  660. generated in a fixed_width font, ignoring the formatting information in the documents.
  661. Examples:
  662.     Edit.Print PostScript0 *
  663.     Edit.Print PostScript1 % File1 File2 File3 ~
  664. 5.  MACINTOSH TOOLBOX INTERFACES
  665. 5.0.  Overview
  666. A skeletal Toolbox interface is provided in source form along with MacOberon.  The
  667. modules provided may simply be augmented as necessary and new ones may be
  668. created easily when required.
  669. It is advantageous to employ a module organization that reflects the decomposition
  670. of the Toolbox into distinct "managers" (i.e. chapters in the Inside Macintosh
  671. documentation).  However, there is a need for a basic module supplying some data
  672. types which are used throughout the Macintosh Toolbox interface.  Only the type
  673. definitions of this basic module, MacTypes (which should be left unchanged), and
  674. excerpts of the interfaces to QuickDraw and the Window Manager are listed here.  There
  675. are more such modules on the MacOberon distribution disk.
  676. The outline of an exemplary Macintosh application written in Oberon concludes
  677. this chapter.
  678. 5.1.  Macintosh Toolbox Types
  679. MODULE MacTypes;   (* Macintosh Operating System and Toolbox Interface Base Module *)
  680.     TYPE
  681.         UnpackedChar*= INTEGER;    (* Macintosh Character Type *)
  682.         PackedChar*= SHORTINT;    (* Character Type as Element of PACKED ARRAY *)
  683.         UnpackedByte*= INTEGER;    (* Should be Subrange [0..255] of INTEGER *)
  684.         PackedByte*= SHORTINT;    (* Byte as Element of PACKED ARRAY *)
  685.         SignedByte*= SHORTINT;    (* Any byte in memory *)
  686.         Fixed*= LONGINT;    (* Fixed point arithmetic type *)
  687.         Data*= RECORD + END;    (* Base Type of Anything *)
  688.         Ptr*= POINTER + TO Data;    (* Blind pointer *)
  689.         Anchor*= RECORD + p*: Ptr END;    (* Container for master pointer *)
  690.         Handle*= POINTER + TO Anchor;    (* Pointer to a master pointer ['s container] *)
  691.         Point*= RECORD + v*, h*: INTEGER END;
  692.         Rect*= RECORD + top*, left*, bottom*, right*: INTEGER END;
  693.         Str255*= ARRAY + 256 OF PackedChar;
  694.         StringPtr*= POINTER + TO Str255;
  695.         StringAnchor*= RECORD + p*: StringPtr END;
  696.         StringHandle*= POINTER + TO StringAnchor;
  697. END MacTypes.
  698. MacTypes defines some data types which are used throughout the Toolbox interface. 
  699. Particularly convenient for low_level Macintosh programming is the empty record type
  700. "Data" and and its associated pointer type "Ptr".  It can be used for correctly
  701. dereferencing pointers or handles to "raw" data.  We may declare extensions of "Data"
  702. for each data structure in memory that we wish to access via such pointers.  An
  703. appropriate type guard can then be applied to the pointer type because type guards
  704. never fail when applied to interfacing types.  This mechanism therefore has the same
  705. effect as type_casting of pointers in Pascal and is also similar syntactically.  It is also
  706. useful for simulating Pascal's variant records in Oberon.
  707. Example:
  708.     TYPE Peek = RECORD +
  709.         (MacTypes.Data)
  710.         byte: SHORTINT
  711. MacTypes also illustrates how to simulate the data type "Handle", a pointer to a pointer,
  712. by the use of an intermediate record which we call "Anchor".  A common base type for
  713. all Anchors is not desirable as it eliminates type checking in places where this might be
  714. helpful.
  715. Conversion between the MacTypes.Str255 string format and the zero_terminated
  716. string format that Oberon uses may be achieved by use of the following two procedures
  717. which are included in module MacTypes on the distribution disk.  Note that the
  718. Toolbox uses a different representation than Oberon for Characters and Bytes that are
  719. not elements of arrays.
  720.     PROCEDURE SetStr255(chars: ARRAY OF CHAR; VAR theStr255: MacTypes.Str255);
  721.         VAR i: INTEGER; ch: CHAR;
  722.     BEGIN  i := 0;
  723.         REPEAT  ch := chars[i]; INC(i); theStr255[i] := SHORT(ORD(ch))  UNTIL  (ch = 0X) OR (i=256);
  724.         theStr255[0] := SHORT(i-1)
  725.     END SetStr255;
  726.     PROCEDURE GetStr255(VAR theStr255: MacTypes.Str255; VAR chars: ARRAY OF CHAR);
  727.         VAR n: INTEGER; ch: CHAR;
  728.     BEGIN  n := theStr255[0];
  729.         IF  LEN(chars) < n  THEN  n := SHORT(LEN(chars))  END;
  730.         WHILE  n > 0  DO  ch := CHR(theStr255[n]); DEC(n); chars[n] := ch  END
  731.     END GetStr255;
  732. 5.2.  Macintosh QuickDraw
  733. Module MacQuickDraw presents a possible interface to the built_in graphics routines of
  734. the Macintosh.  It contains examples of in_line procedure declarations and
  735. demonstrates how to access the global variables of QuickDraw from Oberon.  A pointer
  736. to the end of this global variable block is maintained by the Macintosh operating
  737. system and stored at the address that the processor's address register A5 points to.
  738. MODULE MacQuickDraw;   (* Excerpt of a Macintosh Toolbox Interface Module *)
  739.     IMPORT
  740.         TY:= MacTypes, SYSTEM;
  741.     CONST
  742.         srcCopy*= 0; srcOr*= 1; srcXor*= 2; srcBic*= 3; ...        (* Transfer Modes *)
  743.     TYPE
  744.         Pattern*= ARRAY + 8 OF TY.PackedByte;
  745.         BitMap*= RECORD +
  746.             baseAddr*: TY.Ptr;
  747.             rowBytes*: INTEGER;
  748.             bounds*: TY.Rect
  749.         END;
  750.         Cursor*= RECORD +
  751.             data*, mask*: ARRAY + 16 OF INTEGER;
  752.             hotSpot*: TY.Point
  753.         END;
  754.         GrafPtr*= POINTER + TO GrafPort;
  755.         GrafPort*= RECORD +
  756.             device*: INTEGER;
  757.             ...
  758.         END;
  759.         GlobalsPtr* = POINTER + TO Globals;    (* Initialized to 0(A5) - 126 *)
  760.         Globals* = RECORD +
  761.             (TY.Data)        (* QD offsets *)    (* Oberon offsets *)
  762.             randSeed*: LONGINT;    (* -126 *)    (* 0 *)
  763.             screenBits*: BitMap;    (* -122 *)    (* 4 *)
  764.             arrow*: Cursor;        (* -108 *)    (* 18 *)
  765.             dkGray*, ltGray*, gray*, black*, white*: Pattern;    (* -40, ..., -8 *)    (* 86, ..., 118 *)
  766.             thePort*: GrafPtr        (* 0 *)    (* 126 *)
  767.         END;
  768.         globals*: GlobalsPtr;
  769.     PROCEDURE - SetPort*(port: GrafPtr)    0A8H, 073H;
  770.     PROCEDURE - GetPort*(VAR port: GrafPtr)    0A8H, 074H;
  771. BEGIN
  772.     SYSTEM.GETREG(13, globals);
  773.     SYSTEM.GET(SYSTEM.VAL(LONGINT, globals), globals);    (* Mem[ 0(A5) ] *)
  774.     DEC(SYSTEM.VAL(LONGINT, globals), 126)
  775. END MacQuickDraw.
  776. 5.3.  Macintosh Window Manager
  777. MODULE MacWindows;   (* Excerpt of a Macintosh Toolbox Interface Module *)
  778.     IMPORT
  779.         TY:= MacTypes, QD:= MacQuickDraw;
  780.     CONST
  781.         dialogKind*= 2; userKind*= 8;   (* Window Kind *)
  782.     TYPE
  783.         WindowPtr*= POINTER + TO WindowRecord;
  784.         WindowRecord*= RECORD +
  785.             (QD.GrafPort)
  786.             windowKind*: INTEGER;
  787.             visible*, hilited*, goAwayFlag*, spareFlag*: BOOLEAN;
  788.             ...
  789.         END;
  790.     PROCEDURE - ShowWindow*(theWindow: WindowPtr)  0A9H, 015H;
  791.     PROCEDURE - HideWindow*(theWindow: WindowPtr)  0A9H, 016H;
  792. END MacWindows.
  793. Module MacWindows contains an example of how type extension may be used for
  794. simulating variant records.  This example shows that in many cases type extension is a
  795. natural concept and well suited for expressing certain kinds of type association.  We
  796. have declared a WindowRecord as an extension of a QuickDraw.GrafPort, whereas in the
  797. original Toolbox definition the WindowRecord contains a GrafPort as its first field
  798. which is an unnatural representation of the interrelationship between the two types.
  799. 5.4.  A Sample Application
  800. A module SampleApp is partly listed below which exports a command SampleApp.Loop,
  801. embedded inside of which is an event loop similar to that of typical Macintosh
  802. Applications.
  803. Modules such as SampleApp may display private cursors and unique menus which
  804. can be built directly or read from a resource file.  The procedures below demonstrate
  805. how this is done.  MacOberon uses resource numbers greater than 32000 while the
  806. Operating System reserves all numbers smaller than 128.  Resource numbers between
  807. 128 and 32000 may be assigned freely.
  808. MODULE SampleApp;    (* Sample Macintosh Application Running under MacOberon *)
  809. IMPORT
  810.     SYSTEM, OberonDisplay:= Display,
  811.     TY:= MacTypes, DL:= MacDialogs, DS:= MacDesk, EM:= MacEvents,
  812.     MN:= MacMenus, QD:= MacQuickDraw, WM:= MacWindows;
  813. CONST  (* Resource ID definitions. *)
  814.     AboutAlert= 128;
  815.     AppleMenu= 128; AboutItem= 1;
  816.     FileMenu= 129; QuitItem= 1;
  817.     EditMenu= 130; (* Undo ;- Cut Copy Paste Clear *)
  818.     SampleMenu= 131; DoItItem= 1;
  819.     terminate: BOOLEAN;  (* Return to Oberon on next Loop iteration when TRUE *)
  820. (* Procedures that perform different actions depending on a window classification *)
  821.     PROCEDURE Close(window: WM.WindowPtr);    (* Close window *)
  822.     BEGIN
  823.         IF  IsOberonWindow(window)  THEN  OberonDisplay.Hide
  824.         ELSIF  IsDAWindow(window)  THEN  DS.CloseDeskAcc(window.windowKind)
  825.         ELSIF  IsSampleWindow(window)  THEN  WM.CloseWindow(window)
  826.         END
  827.     END Close;
  828.     PROCEDURE Update(window: WM.WindowPtr);    (* Update window contents *)
  829.     BEGIN
  830.         IF  IsOberonWindow(window)  THEN  OberonDisplay.Update
  831.         ELSIF  IsSampleWindow(window)  THEN
  832.             WM.BeginUpdate(window);  ...  WM.EndUpdate(window)
  833.         END
  834.     END Update;
  835. (* Procedures that do something useful and distinguish Sample from other applications *)
  836.     PROCEDURE DoIt*;    (* Activated when the user chooses DoIt from the menu *)
  837.     BEGIN
  838.         ...
  839.     END DoIt; 
  840. (* Procedures that are required in all applications in some form *)
  841.     PROCEDURE Terminate;    (* Close all windows and set Termination Flag *)
  842.         VAR aWindow: WM.WindowPtr;
  843.     BEGIN  terminate := TRUE; aWindow := WM.FrontWindow();
  844.         WHILE  aWindow # NIL  DO  Close(aWindow); aWindow := WM.FrontWindow()  END
  845.     END Terminate;
  846. (* User Input and Command Distribution *)
  847.     PROCEDURE MenuCommand(menuResult: LONGINT);
  848.         VAR    menuID, menuItem: INTEGER;
  849.                 daName: TY.Str255; daRefNum, itemHit: INTEGER; handledByDA: BOOLEAN;
  850.     BEGIN  menuID := SHORT(menuResult DIV 10000H);
  851.         menuItem := SHORT(menuResult MOD 10000H);
  852.         CASE  menuID  OF
  853.         |    MN.NoMenu:
  854.         |    AppleMenu:
  855.                 IF  menuItem = AboutItem  THEN  itemHit := DL.Alert(AboutAlert, NIL)
  856.                 ELSE  MN.GetItem(MN.GetMHandle(AppleMenu), menuItem, daName);
  857.                     daRefNum := DS.OpenDeskAcc(daName)
  858.                 END
  859.         |    FileMenu:
  860.                 IF  menuItem = QuitItem  THEN  Terminate  END
  861.         |    EditMenu:
  862.                 IF  IsDAWindow(WM.FrontWindow())  THEN
  863.                     handledByDA := DS.SystemEdit(menuItem-1)
  864.                 END
  865.         |    SampleMenu:
  866.                 IF  menuItem = DoItItem  THEN  DoIt  END
  867.         END;
  868.         MN.HiliteMenu(MN.NoMenu)
  869.     END MenuCommand;
  870.     PROCEDURE Loop*();    (* Main Loop, activated as a Command *)
  871.         VAR gotEvent: BOOLEAN; event: EM.EventRecord; window: WM.WindowPtr;
  872.     BEGIN  SetupSampleLooks; terminate := FALSE;
  873.         REPEAT  gotEvent := EM.WaitNextEvent(EM.everyEvent, event, 0, NIL);
  874.             CASE  event.what  OF    (* Dispatch on event type *)
  875.             |    EM.updateEvt:
  876.                     Update(SYSTEM.VAL(WM.WindowPtr, event.message))
  877.             |    EM.mouseDown:
  878.                     CASE WM.FindWindow(event.where, window) OF
  879.                     |    WM.inMenuBar:
  880.                             MenuCommand(MN.MenuSelect(event.where))
  881.                     |    WM.inContent:
  882.                             IF  window # WM.FrontWindow()  THEN  WM.SelectWindow(window)  END
  883.                     |    WM.inDrag:
  884.                             WM.DragWindow(window, event.where, QD.globals.screenBits.bounds)
  885.                     |    WM.inGoAway:
  886.                             Close(window)
  887.                     ...
  888.                     END;
  889.             ...
  890.             END
  891.         UNTIL  terminate;
  892.         RestoreOberonLooks
  893.     END Loop;
  894. END SampleApp.
  895. The main loop of Oberon automatically reinstates Oberon's cursor shape and menu
  896. layout if these have inadvertently not been restored by user commands.  Consequently,
  897. commands which change the appearance of cursor and menus, such as the procedures
  898. SetupSampleLooks and RestoreOberonLooks below, may be executed for testing
  899. purposes without danger of disrupting the correct functioning of the MacOberon
  900. application.
  901.     PROCEDURE SetupSampleLooks*;
  902.         VAR resName: MacTypes.Str255; menuBar: MacTypes.Handle;
  903.     BEGIN  MacTypes.SetStr255("SampleApp.r", resName);
  904.         theResFile:= RM.OpenResFile(resName);
  905.         menuBar := MN.GetNewMBar(MBarResNo);
  906.         MN.SetMenuBar(menuBar); MN.DrawMenuBar;
  907.         QD.SetCursor(QuickDraw.globals.arrow);
  908.         OberonDisplay.Hide
  909.     END SetupSampleLooks;
  910.     PROCEDURE RestoreOberonLooks*;
  911.     BEGIN  RM.CloseResFile(theResFile);
  912.         OberonDisplay.ShowStdMenus; OberonDisplay.ShowStdArrow; OberonDisplay.Show
  913.     END RestoreOberonLooks;
  914. Macintosh Applications are structured differently from Oberon programs, in that
  915. windows on the screen are not active objects and don't contain a handler to which
  916. control can be delegated when an event for the window has arrived.  Instead, the main
  917. loop in such applications has to classify the window and then decide what kind of
  918. action to perform.  In SampleApp we differentiate between the Oberon Display, Desk
  919. Accessories and the windows opened by SampleApp itself.  The corresponding
  920. classification procedures are shown below.
  921. PROCEDURE IsOberonWindow(window: WM.WindowPtr): BOOLEAN;  (* Shell window? *)
  922. BEGIN  RETURN window=SYSTEM.VAL(WM.WindowPtr, OberonDisplay.window)
  923. END IsOberonWindow;
  924. PROCEDURE IsDAWindow(window: WM.WindowPtr): BOOLEAN;  (* Desk Accessory window? *)
  925. BEGIN  RETURN (window # NIL) & (window.windowKind < 0)    
  926. END IsDAWindow;
  927. PROCEDURE IsSampleWindow(window: WM.WindowPtr): BOOLEAN;  (* Sample's window? *)    
  928. BEGIN
  929.     RETURN (window # NIL) & ~IsOberonWindow(window) &
  930.         ((window.windowKind >= WM.userKind) OR (window.windowKind = WM.dialogKind))
  931. END IsSampleWindow;
  932. Debugging programs such as SampleApp in Oberon is simplified greatly by exporting
  933. individual functions as commands while the application is being developed (e.g.
  934. SampleApp.DoIt).  The constituents of the application may thus be tested separately
  935. without the burden of a central loop.
  936. APPENDIX
  937. Oberon Symbol Files
  938. The following tables define the format of Oberon symbol files in EBNF notation. 
  939. Names are sequences of characters (bytes) terminated by 0X.  Lower case identifiers
  940. denote numbers, the length of which (in bytes) is appended to the name.
  941. SymFile    =    SFtag ModAnchor {Element}.
  942. SFtag    =    0FAX.
  943. ModAnchor    =    MOD key4 name.
  944. Element    =    ModAnchor
  945.     |    CON Constant
  946.     |    (TYPE | HDTYPE) Type
  947.     |    (VAR | FLD) Variable
  948.     |    (VALPAR | VARPAR) Parameter
  949.     |    PLIST {Element} (XPRO | IPRO) Procedure
  950.     |    PLIST {Element} CPRO CProcedure
  951.     |    PTR PointerType
  952.     |    PLIST {Element} PROC ProcType
  953.     |    ARR ArrayType
  954.     |    DARR DynArrType
  955.     |    FLIST {Element} REC RecordType
  956.     |    (HDPTR | HDPROC) HiddenFldOff
  957.     |    FIX Fixup
  958.     |    SYS Flag.
  959. Constant    =    (BYTE | BOOL | CHAR | SINT) value1 name
  960.     |    INT value2 name
  961.     |    (LINT | REAL | SET) value4 name
  962.     |    LREAL value8 name
  963.     |    STRING name name
  964.     |    NIL name.
  965. Type    =    ref1 modno1 name.
  966. Variable    =    ref1 offset4 name.
  967. Parameter    =    ref1 offset2 name.
  968. Procedure    =    ref1 procno1 name.
  969. CProcedure    =    ref1 len1 {code1} name.
  970. PointerType    =    baseRef1 modno1.
  971. ProcType    =    resultRef1 modno1.
  972. ArrayType    =    elemRef1 modno1 size4 boundAdr2 nofElem4.
  973. DynArrType    =    elemRef1 modno1 size4 lenOff2.
  974. RecordType    =    baseRef1 modno1 size4 descAdr2.
  975. HiddenFldOff    =    offset4.
  976. Fixup    =    ptrRef1 baseRef1.
  977. Flag    =    ref1 sysflag2.
  978. Two values for the field sysflag in structure descriptions are defined in the first release of
  979. MacOberon:  A value of zero denotes standard MacOberon structures, whereas a value
  980. of one indicates data structures that have an internal layout according to Macintosh
  981. Toolbox conventions.
  982. CON    =    1.    FLIST    =    16.    Predefined References:
  983. TYPE    =    2.    FLD    =    17.
  984. HDTYPE    =    3.    HDPTR    =    18.    UNDEF    =    0.
  985. VAR    =    4.    HDPROC    =    19.    BYTE    =    1.
  986. XPRO    =    5.    FIX    =    20.    BOOL    =    2.
  987. IPRO    =    6.    SYS    =    21.    CHAR    =    3.
  988. CPRO    =    7.    MOD    =    22.    SINT    =    4.
  989. PTR    =    8.                INT    =    5.
  990. PROC    =    9.                LINT    =    6.
  991. ARR    =    10.                REAL    =    7.
  992. DARR    =    11.                LREAL    =    8.
  993. REC    =     12.    Boolean Constants:    SET    =    9.
  994. PLIST    =    13.                STRING    =    10.
  995. VALPAR    =    14.    FALSE    =    0X    NIL    =    11.
  996. VARPAR    =    15.    TRUE    =    1X    NOTYP    =    12.
  997.